import SwiftUI
import WidgetKit
import CalendarShared

public struct ScreenView: View {
    public enum Style {
        case taboo
        case festival
    }

    @Environment(\.widgetFamily) var family
    @Environment(\.colorScheme) var colorScheme
    public let entry: ScreenEntry
    public let style: Style
    private let suitable: String
    private let taboo: String
    private let tabooLunar: String
    private let progress: Double
    private let festival: String
    private let tiaoxiu: DayModel.TiaoXiu
    private let week: String

    public init(entry: ScreenEntry, style: Style = .taboo) {
        self.entry = entry
        let heavenlyStems = entry.date.heavenlyStems
        let earthlyBranches = entry.date.earthlyBranches
        let zodiac = entry.date.zodiac
        let month = entry.date.lunarMonthString
        let day = entry.date.lunarDayString(false)
        self.progress = Double(entry.date.day) / Double(entry.date.dayCount)
        let dayModel = CalendarShared.shared.getDay(entry.date)
        let hasFestival = dayModel.festivals.first != nil || dayModel.isFestival
        self.tabooLunar = hasFestival ? (heavenlyStems + earthlyBranches + zodiac + month + day) : (heavenlyStems + earthlyBranches + zodiac)
        let festival = dayModel.festivals.first ?? dayModel.lunar
        self.festival = hasFestival ? festival : month + dayModel.lunar
        self.suitable = dayModel.suitable.prefix(count: 2, maxLength: 2).joined(separator: " ")
        self.taboo = dayModel.taboo.prefix(count: 2, maxLength: 2).joined(separator: " ")
        self.tiaoxiu = dayModel.tiaoxiu
        self.style = style
        var weekStr = Week.allCases[entry.date.weekday].fullName(entry.language)
        let weekOfMonth = dayModel.date.weekOfMonth
        if entry.language.isEnglish {
            weekStr = Week.allCases[entry.date.weekday].title(entry.language)
            let str = String(format: NSLocalizedString("BearCalendar.week.month", bundle: .module, comment: "第几周"), weekOfMonth)
            weekStr += " · " + str
        } else {
            let weeks = ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十"]
            if weeks.count > weekOfMonth, weekOfMonth > 0 {
                let value = weeks[weekOfMonth - 1]
                let str = String(format: NSLocalizedString("BearCalendar.week.month", bundle: .module, comment: "第几周"), value)
                weekStr += " · " + str
            }
        }
        week = weekStr
    }

    public var body: some View {
        Group {
            switch family {
            case .accessoryCircular:
                HStack {
                    accessoryCircular
                }
            case .accessoryRectangular:
                switch style {
                case .taboo:
                    tabooView
                case .festival:
                    festivalView
                }
            default: EmptyView()
            }
        }
        .widgetBackground(Color.clear)
    }
}

extension ScreenView {
    @ViewBuilder
    var accessoryCircular: some View {
        let yearMonth = String(format: "%zi-%02zi", entry.date.year, entry.date.month)
        let day = String(format: "%zi", entry.date.day)
        ZStack {
            Gauge(
                value: progress,
                label: {  },
                currentValueLabel: {
                    switch tiaoxiu {
                    case .none:
                        Text(day).font(.system(size: 20, weight: .bold))
                    case .work:
                        Image("work")
                            .resizable()
                            .frame(width: 20, height: 20)
                    case .rest:
                        Image("rest")
                            .resizable()
                            .frame(width: 20, height: 20)
                    }
                }
            )
            .gaugeStyle(.accessoryCircular)
            .tint(Gradient(colors: [.green, .yellow, .orange, .red]))
            VStack {
                Spacer()
                Text(yearMonth).font(.system(size: 8, weight: .bold))
            }
        }
    }

    var tabooView: some View {
        VStack(alignment: .leading) {
            HStack {
                accessoryCircular
                VStack(alignment: .leading) {
                    Text(tabooLunar).font(.system(size: 12, weight: .regular))
                    HStack(spacing: 4) {
                        Text("宜: ").font(.system(size: 12, weight: .bold))
                        Text(suitable).font(.system(size: 12, weight: .regular))
                    }
                    HStack(spacing: 4) {
                        Text("忌: ").font(.system(size: 12, weight: .bold))
                        Text(taboo).font(.system(size: 12, weight: .regular))
                    }
                }
            }
            HStack {
                Text(festival)
                    .font(.system(size: 12, weight: .regular))
            }
            .frame(height: 12)
        }
    }

    var festivalView: some View {
        VStack(alignment: .leading) {
            HStack {
                accessoryCircular
                VStack(alignment: .leading) {
                    HStack {
                        Text(week)
                            .font(.system(size: 12, weight: .regular))
                    }
                    .frame(height: 12)
                    HStack {
                        Text(tabooLunar)
                            .font(.system(size: 12, weight: .regular))
                    }
                    .frame(height: 12)
                }
                Spacer()
            }
            HStack {
                Text(festival)
                    .font(.system(size: 12, weight: .regular))
                Spacer()
            }
            .frame(height: 12)
        }
    }
}

extension ScreenView {
    func weekColor(_ entry: TimelineEntry & CalendarEntryable, dayModel: DayModel) -> Color {
        if dayModel.date.isWeekDay {
            entry.week.color(colorScheme)
        } else {
            entry.normal.color(colorScheme)
        }
    }

    func festivalColor(_ entry: TimelineEntry & CalendarEntryable, dayModel: DayModel) -> Color {
        if dayModel.isFestival {
            entry.festival.color(colorScheme)
        } else {
            entry.normal.color(colorScheme)
        }
    }
}

